package cn.golxen.blog.redis;

import cn.golxen.blog.commons.rabbitVo.*;
import cn.golxen.blog.commons.utils.JSONUtils;
import cn.golxen.blog.commons.vo.*;
import cn.golxen.blog.entity.Essay;
import cn.golxen.blog.exception.exceptionClass.GetEssayEmptyException;
import cn.golxen.blog.mapper.EssayLabelMapper;
import cn.golxen.blog.mapper.EssayMapper;
import cn.golxen.blog.rabbitMQ.producer.Producer;
import com.alibaba.fastjson.JSONObject;
import com.github.pagehelper.Page;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Component;

import java.util.*;
import java.util.concurrent.TimeUnit;

@Slf4j
@Component
public class EssayRedis {

    @Autowired
    @Qualifier(value = "taskExecutor")
    private ThreadPoolTaskExecutor poolTaskExecutor;
    @Autowired
    RedisTemplate<String,String> redisTemplate;
    @Autowired
    EssayMapper essayMapper;
    @Autowired
    Producer producer;
    @Autowired
    EssayLabelMapper essayLabelMapper;



    public ResPageListVo getList(PageListVo pageListVo, Page<?> pageInfo){
        String page=pageListVo.getPage().toString();
        Set<String> set= redisTemplate.opsForZSet().range("essayList" + page, 0, -1);
//        if (Boolean.TRUE.equals(redisTemplate.hasKey("essayList"+page))){
        if (set!=null&&!set.isEmpty()){
            log.info("走redis了");
//        if (false){
//            System.out.println("走redis了");
//            Long datetime = System.currentTimeMillis();
//            Set<String> set= redisTemplate.opsForZSet().range("essayList" + page, 0, -1);
//            Long datetime2 = System.currentTimeMillis();
//            System.out.println(datetime2-datetime);
//            List<String> list=new ArrayList<>(set);
            Essay essay=new cn.golxen.blog.entity.Essay();
            List<Essay> essayList=new ArrayList<>();
            for (Object o : set) {
                essay = JSONObject.parseObject(o.toString(), cn.golxen.blog.entity.Essay.class);
                essayList.add(essay);
            }
            long total=Long.parseLong(Objects.requireNonNull(redisTemplate.opsForValue().get("pagetotal")));

            ResPageListVo resPageListVo=new ResPageListVo(page,total, essayList);
            return resPageListVo;
        }else {
            log.info("走mysql了");
//            Long datetime = System.currentTimeMillis();
            List<cn.golxen.blog.entity.Essay> list=essayMapper.getList();
//            Long datetime2 = System.currentTimeMillis();
//            System.out.println(datetime2-datetime);
            String totalStr=Long.toString(pageInfo.getTotal());
            poolTaskExecutor.execute(() -> {
                producer.essayProducer(new AddRedisEssayListVo(page,totalStr,list));
            });
            ResPageListVo resPageListVo=new ResPageListVo(page,pageInfo.getTotal(),list);
//            System.out.println("后");
            return resPageListVo;
        }
    }

    public void deleteEssay(List<String> list){
        Set<String> set= new HashSet<>(list);
        producer.essayProducer(new DeleteRedisEssayVo(set));
    }
    public void deleteEssay(){
        producer.essayProducer(new DeleteRedisEssayVo());
    }

    public void deleteEssayByCategoryAndLabel(String category){
        producer.essayProducer(new DeleteRedisEssayByCategoryAndLabelVo(category));
    }
    public void deleteEssayByCategoryAndLabel(){
        log.info("走无参构造");
        producer.essayProducer(new DeleteRedisEssayByCategoryAndLabelVo());
    }
    public void deleteLabelByEssay(Set<String> essayIdSet){
        producer.essayProducer(new DeleteRedisLabelByEssayVo(essayIdSet));
    }


    public Essay getEssayById(String id){
        Set<String> essaySet=redisTemplate.keys("id:"+id+"*");
        if(essaySet!=null&&!essaySet.isEmpty()){
            String key=essaySet.stream().iterator().next();
            String essayStr=redisTemplate.opsForValue().get(key);
            log.info("走redis了");
            return JSONObject.parseObject(essayStr,Essay.class);
        }else{
            Essay essay=essayMapper.getEssayById(id);
            poolTaskExecutor.execute(()->{
                producer.essayProducer(new AddRedisEssayVo(essay));
            });
            log.info("走MySQL了");
            return essay;
        }
    }

    public Integer updateView(String essayId){
        if (Boolean.TRUE.equals(redisTemplate.hasKey("viewsId:" + essayId))){
            Integer integer=Objects.requireNonNull(redisTemplate.opsForValue().increment("viewsId:" + essayId)).intValue();
            redisTemplate.opsForValue().increment("viewsId_2:" + essayId);
//            if(integer%10==0){
//                poolTaskExecutor.execute(()->{
//                    producer.essayProducer(new UpdateMySqlViewsVo(essayId,integer));
//                });
//            }
            return integer;
        }else{
            Integer views=essayMapper.getViewById(essayId);
            redisTemplate.opsForValue().setIfAbsent("viewsId:"+essayId,String.valueOf(views),3600, TimeUnit.SECONDS);
            redisTemplate.opsForValue().setIfAbsent("viewsId_2:"+essayId,String.valueOf(views));

            Integer integer= Objects.requireNonNull(redisTemplate.opsForValue().increment("viewsId:" + essayId)).intValue();
            redisTemplate.opsForValue().increment("viewsId_2:" + essayId);
            return integer;
        }
    }

    public Integer getCountOfCategory(String category){
        String count=redisTemplate.opsForValue().get("category:"+category+":count_essay");
        if (count!=null&&!count.isEmpty()){
            log.info("走redis");
        }else {
            log.info("走mysql");
            count= String.valueOf(essayMapper.getCountOfCategory(category));
//            redisTemplate.opsForValue().set("category:"+category+":essay",count);
            String finalCount = count;
            poolTaskExecutor.execute(()->{
                producer.essayProducer(new AddRedisCountOfCategoryVo(finalCount,category));
            });
        }
        return Integer.valueOf(count);
    }

    public Set<Essay> getEssaySetByCategory(String category){
        Set<String> set=redisTemplate.opsForSet().members("category:"+category+":essay_set");
        Set<Essay> essaySet;
        if (set!=null&&!set.isEmpty()){
            log.info("走redis");
            essaySet = JSONUtils.JSONSetToEssaySet(set);

        }else {
            log.info("走mysql");
            essaySet = essayMapper.getEssaySetByCategory(category);
            poolTaskExecutor.execute(()->{
                producer.essayProducer(new AddRedisEssayByCategoryVo(category,essaySet));
            });
            if (essaySet.isEmpty())
                throw new GetEssayEmptyException();
        }
        return essaySet;

    }

    public Set<Essay> getEssaySetByLabel(String label){
        Set<String> stringSet=redisTemplate.opsForSet().members("label:"+label+":essay_set");
        Set<Essay> essaySet;
        if (stringSet!=null&&!stringSet.isEmpty()){
            log.info("走redis");
            essaySet=JSONUtils.JSONSetToEssaySet(stringSet);


        }else {
            log.info("走mysql");
            essaySet=essayMapper.getEssaySetByLabel(label);
            poolTaskExecutor.execute(()->{
                producer.essayProducer(new AddRedisEssayByLabelVo(label,essaySet));
            });
            if(essaySet.isEmpty())
                throw new GetEssayEmptyException();
        }
        return essaySet;
    }

    public Integer getCount(){
        String countStr=redisTemplate.opsForValue().get("essay_count");
        if (countStr!=null&&!countStr.isEmpty()){
            log.info("走redis");
            return Integer.valueOf(countStr);
        }else {
            log.info("走mysql");
            Integer count=essayMapper.getCount();
            poolTaskExecutor.execute(()->{
                producer.categoryProducer(new AddRedisCountByCategoryOrLabelVo(String.valueOf(count),"essay"));
            });
            return count;
        }
    }

    public Set<String> getLabelByEssayId(String essayId){
        Set<String> labelSet=redisTemplate.opsForSet().members("essay:"+essayId+":label_set");
        if (labelSet!=null&&!labelSet.isEmpty()){
            log.info("走redis");
        }else {
            log.info("走mysql");
            labelSet = essayLabelMapper.getLabelByEssayId(essayId);
            Set<String> finalLabelSet = labelSet;
            poolTaskExecutor.execute(()->{
                producer.essayProducer(new AddRedisLabelByEssayVo(essayId, finalLabelSet));
            });
        }
        return labelSet;
    }

}
